package com.fiona.core.load;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fiona.annotation.FionaApi;
import com.fiona.common.base.config.FionaConfig;
import com.fiona.common.constant.FionaConstant;
import com.fiona.common.constant.FionaSpace;
import com.fiona.core.model.FionaBeanClassModel;
import com.fiona.core.model.FionaBeanModel;
import com.fiona.core.model.FionaMappingModel;
import com.fiona.core.proxy.FionaCglibProxy;
import com.fiona.core.remoting.model.FionaApiServiceObj;
import com.fiona.core.remoting.model.Service;

import cn.hutool.core.util.StrUtil;

/**
 * 加载所有的FionaApi，并完成注入
 * 
 * @author huacongnan
 *
 */
public class LoadFionaApi {

	/**
	 * 获取全局存储空间
	 */
	private static FionaSpace constants = FionaSpace.getFionaSpace();

	/**
	 * 创建FionaApi对象，并将服务层对象注入进去
	 */
	public static void loadFionaApis() throws Exception {

		try {
			/* 创建一个Map用来储存API信息 */
			Map<String, FionaMappingModel> fionaApiObjects = new HashMap<>();

			/* 获取所有的FionaApi数据 */
			List<FionaBeanClassModel> fionaApiList = LoadHelper.getFionaApiList();

			/* 获取所有的FionaBean */
			Map<String, FionaBeanModel> fionaBeanObjs = LoadHelper.getBeanObjectMap();

			for (FionaBeanClassModel fionaBeanClassModel : fionaApiList) {

				Class<?> cls = fionaBeanClassModel.getClassName();
				FionaApi fionaApi = (FionaApi) fionaBeanClassModel.getAnnotation();

				/*
				 * 由于FionaApi里只允许注入FionaBean，所以不需要等FionaApi都创建好了再注入 直接 迭代一次 就给一个FionaApi注入一次
				 */
				Object obj = iocFionaApi(cls, fionaBeanObjs);

				// 获取API实现类服务名称，没有配置默认取实现类名称（首字母小写处理）
				String apiName = fionaApi.name();
				if (StrUtil.isEmpty(apiName)) {
					apiName = StrUtil.lowerFirst(cls.getSimpleName());
				}
				String interfaceName = fionaApi.interfaceName();
				if (StrUtil.isEmpty(interfaceName)) {
					Class<?>[] ia = cls.getInterfaces();
					if (ia.length == 0) {
						throw new IllegalStateException(String.format("%s has no interface", apiName));
					}
					interfaceName = ia[0].getName();
				}
				Service service = new Service();
				service.setInterfaceName(interfaceName);
				service.setName(apiName);
				service.setVersion(fionaApi.version());
				service.setAddress(FionaConfig.getServerAddress().toString());
				service.setWeight(0);
				service.setClazz(cls);
				service.setObj(obj);
				FionaApiServiceObj.putService(service.getServiceId(), service);
//				/* 获取FionaApi的所有方法 */
//				Method[] methods = cls.getMethods();
//				for (Method method : methods) {
//					if (method.getDeclaringClass().equals(cls)) {
//						/* 创建映射对象 */
//						FionaMappingModel fionaMappingModel = new FionaMappingModel();
//						fionaMappingModel.setObject(obj);
//						fionaMappingModel.setMethod(method.getName());
//						fionaMappingModel.setCls(cls);
//						fionaMappingModel.setExeMethod(method);
//						/* 保存映射对象 */
//						// IService-serviceName-version-methodName
//						fionaApiObjects.put(
//								interfaceName.concat(FionaConstant.STRIKETHROUGH).concat(apiName)
//										.concat(FionaConstant.STRIKETHROUGH).concat(fionaApi.version())
//										.concat(FionaConstant.STRIKETHROUGH).concat(method.getName()),
//								fionaMappingModel);
//					}
//				}
			}

//			constants.setAttr(FionaConstant.FIONA_API_OBJECTS, fionaApiObjects);
		} catch (Exception e) {
			throw new Exception("加载FionaApi并注入的时候报错", e);
		}
	}

	/**
	 * 往FionaApi对象中注入bean
	 * 
	 * @param cls           类
	 * @param fionaBeanObjs 对象
	 * @return 对象
	 */
	private static Object iocFionaApi(Class<?> cls, Map<String, FionaBeanModel> fionaBeanObjs) throws Exception {

		try {
			FionaCglibProxy fionaCglibProxy = new FionaCglibProxy();
			Object obj = fionaCglibProxy.getProxy(cls);

			if (!cls.isInterface()) {
				/* 获取对象属性，完成注入 */
				WriteFields.writeFields(cls, obj, fionaBeanObjs);
			}
			return obj;
		} catch (Exception e) {
			throw new Exception("创建FionaApi并注入的时候报错", e);
		}
	}

}
